package com.syjy.tunnelworker.gathers.iml;


import com.syjy.DataExchangeException;
import com.syjy.container.ProtocolDataContainer;
import com.syjy.tunnelinfo.DataPoint;
import com.syjy.tunnelinfo.TunnelStatus;
import com.syjy.tunnelinfo.gathertunnelinfo.GatherModbusTcpTunnelInfo;
import com.syjy.tunnelworker.BaseProtocolTunnel;
import com.syjy.tunnelworker.gathers.DataGatherInterface;
import com.syjy.tunnelworker.workassist.SingleThreadPoolExecutorUtil;
import wei.yigulu.modbus.domain.FunctionCode;
import wei.yigulu.modbus.domain.Obj4RequestCoil;
import wei.yigulu.modbus.domain.Obj4RequestRegister;
import wei.yigulu.modbus.domain.datatype.BooleanModbusDataInRegister;
import wei.yigulu.modbus.domain.datatype.IModbusDataType;
import wei.yigulu.modbus.domain.datatype.ModbusDataTypeEnum;
import wei.yigulu.modbus.domain.datatype.NumericModbusData;
import wei.yigulu.modbus.exceptiom.ModbusException;
import wei.yigulu.modbus.netty.HSModbusTcpMasterBuilder;
import wei.yigulu.modbus.utils.ModbusRequestDataUtils;
import wei.yigulu.netty.MasterInterface;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * modbus协议TCP数据采集
 *
 * @author 修唯xiuwei
 * @version 3.0
 */

public class ModbusTcpDataGather extends AbstractModbusDataGather<GatherModbusTcpTunnelInfo, HSModbusTcpMasterBuilder> {

	/**
	 * 构造方法
	 *
	 * @param gatherModbusTcpTunnelInfo 通道信息
	 */
	public ModbusTcpDataGather(final GatherModbusTcpTunnelInfo gatherModbusTcpTunnelInfo) {
		super(gatherModbusTcpTunnelInfo);
	}

	@Override
	public ModbusTcpDataGather buildTunnel() throws DataExchangeException {
		protocolBuilder = new ModbusMaster(tunnelInfo.getRemoteIp(), tunnelInfo.getRemotePort());
		protocolBuilder.setSpareIp(tunnelInfo.getRemoteSpareIp());
		protocolBuilder.setSparePort(tunnelInfo.getRemoteSparePort());
		protocolBuilder.setSelfIp(tunnelInfo.getSelfIp());
		protocolBuilder.setSelfPort(tunnelInfo.getSelfPort());
		protocolBuilder.setLog(this.log);
		setSlaveId(this.tunnelInfo.getSlaveId());
		setFunctionCode(FunctionCode.valueOf(this.tunnelInfo.getFunctionCode()));
		setTunnelStatus(TunnelStatus.BUILT);
		protocolTunnelContainer.addTunnel(this);
		parseGatherDataPoint();
		log.info("成功创建ModbusTCPMaster通道对象：{}", this.tunnelInfo.getTunnelName());
		return this;
	}



	@Override
	public ModbusTcpDataGather startTunnel() throws DataExchangeException {
		log.info("modbus TCP master {} 通道开始连接", getTunnelInfo().getTunnelName());
		protocolTunnelContainer.addUpdateDateTask(this);
		try {
			SingleThreadPoolExecutorUtil.executeBySingleThreadExecutor(() -> {
				try {
					this.protocolBuilder.create();
					log.error("modbus TCP master  创建通道失败");
					setTunnelStatus(TunnelStatus.LISTENPORTFAIL);
				} catch (Exception e) {
					log.error("modbus TCP master  创建通道失败", e);
					setTunnelStatus(TunnelStatus.LISTENPORTFAIL);
				}
			});
		} catch (Exception e) {
			log.error("modbus TCP master 创建通道失败", e);
			setTunnelStatus(TunnelStatus.LISTENPORTFAIL);
			throw new DataExchangeException(10007, "modbus TCP master创建通道失败");
		}
		if (!TunnelStatus.LISTENPORTFAIL.equals(getTunnelStatus())) {
			setTunnelStatus(TunnelStatus.LISTENPORTSUCCESS);
		}
		return this;
	}


	@Override
	public BaseProtocolTunnel tunnelStop() throws DataExchangeException {
		if (this.protocolBuilder != null) {
			this.protocolBuilder.stop();
		}
		log.info("关闭 modbus TCP master 通道 {}", this.tunnelInfo.getTunnelName());
		return super.tunnelStop();
	}



	class ModbusMaster extends HSModbusTcpMasterBuilder {

		public ModbusMaster(String ip, Integer port) {
			super(ip, port);
		}

		@Override
		public void connected() {
			setTunnelStatus(TunnelStatus.CONNECTED);
		}

		@Override
		public void disconnected() {
			setTunnelStatus(TunnelStatus.LOSECONN);
		}
	}

}
